//和线程处理逻辑业务相关函数
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <pthread.h>

#include "configure.h"
#include "macro.h"
#include "global.h"
#include "function.h"
#include "mymemory.h"
#include "logic_comm.h"
#include "lock_mutex.h"
#include "crc32.h"
#include "logic_socket.h"

//定义成员函数指针
typedef bool (LogicSocket::*handler)(lpconnection_t connect, LPSTRUC_MSG_HEADER msg_header, char *pkg_body, unsigned short body_length);

static const handler status_handler[] = {
	&LogicSocket::_HandlePing,
	NULL,
	NULL,
	NULL,
	NULL,
	&LogicSocket::_HandleRegister,
	&LogicSocket::_HandleLogIn,
};

#define AUTH_TOTAL_COMMANDS sizeof(status_handler)/sizeof(handler)//一共有多少条命令

LogicSocket::LogicSocket() {

}

LogicSocket::~LogicSocket() {

}

//初始化函数，在fork子进程之前执行
bool LogicSocket::Initialize() {
	bool parent_init = MySocket::Initialize();
	return parent_init;
}

//处理收到的数据包，由线程池调用本函数
void LogicSocket::ThreadRecvProcFunc(char *msg_buf) {
	//LogStderr(0, "线程开始处理消息");
	LPSTRUC_MSG_HEADER msg_header = (LPSTRUC_MSG_HEADER)msg_buf;//消息头
	LPCOMM_PKG_HEADER pkg_header = (LPCOMM_PKG_HEADER)(msg_buf + msg_head_len_);

	void *pkg_body;
	unsigned short pkg_len = ntohs(pkg_header->pkg_len);

	if(pkg_len == pkg_head_len_) {
		//不含有包体
		if(pkg_header->crc32 != 0) {
			//不含有包体的crc32值为0
			return;
		}
		pkg_body = NULL;
	}
	else {
		//有包体，开始处理包体
		pkg_header->crc32 = ntohl(pkg_header->crc32);
		pkg_body = (void*)(msg_buf + msg_head_len_ + pkg_head_len_);//包体

		int compute_crc = CRC32::GetInstance()->GetCrc((unsigned char*)pkg_body, pkg_len - pkg_head_len_);
		if(compute_crc != pkg_header->crc32) {
			LogStderr(0, "LogicSocket::ThreadRecvProcFunc()中CRC错误[服务器:%d,客户端:%d]",compute_crc, pkg_header->crc32);
			return;
		}
		else {
			
		}
	}

	//LogStderr(0, "正常开始处理消息中的内容");
	unsigned short msg_code = ntohs(pkg_header->msg_code);
	lpconnection_t connect = msg_header->connect;

	
	if(connect->current_sequence != msg_header->current_sequence) {
		return;
	}
	//判断消息码是否正确
	if(msg_code >= AUTH_TOTAL_COMMANDS) {
		LogStderr(0, "LogicSocket::ThreadRecvProcFunc()中msg_code=%d消息码不对!", msg_code);
		return;
	}
	if(status_handler[msg_code] == NULL) {
		LogStderr(0, "LogicSocket::ThreadRecvProcFunc()中msg_code=%d消息码找不到对应的处理函数!", msg_code);
		return;
	}

	//LogStderr(0, "消息格式正确，开始调用相应的处理程序");
	
	//调用相应的处理函数
	(this->*status_handler[msg_code])(connect, msg_header, (char *)pkg_body, pkg_len-pkg_head_len_);
	return;
}

//心跳包检测时间
void LogicSocket::ProcPingTimeOutChecking(LPSTRUC_MSG_HEADER tmp_msg, time_t current_time) {
	MyMemory *memory = MyMemory::GetInstance();

	if(tmp_msg->current_sequence == tmp_msg->connect->current_sequence) {
		//连接未断开
		lpconnection_t connect = tmp_msg->connect;
		if(if_timeout_kick_ == 1) {
			ActiveCloseSocketProc(connect);
		}
		else if((current_time - connect->last_ping_time) > (wait_time_*3 + 10)) {
			ActiveCloseSocketProc(connect);
		}
		memory->FreeMemory(tmp_msg);
	}
	else {
		memory->FreeMemory(tmp_msg);
	}
	return;
}


//发送没有包体的数据包给客户端
void LogicSocket::SendNoBodyPkgToClient(LPSTRUC_MSG_HEADER msg_header, unsigned short msg_code) {
	MyMemory *memory = MyMemory::GetInstance();
	char *send_buf = (char *)memory->AllocMemory(msg_head_len_+pkg_head_len_, false);
	char *tmp_buf = send_buf;
	memcpy(tmp_buf, msg_header, msg_head_len_);
	tmp_buf += msg_head_len_;
	
	LPCOMM_PKG_HEADER pkg_header = (LPCOMM_PKG_HEADER)tmp_buf;
	pkg_header->msg_code = htons(msg_code);

	pkg_header->pkg_len = htons(pkg_head_len_);
	pkg_header->crc32 = 0;

	MsgSend(send_buf);
	return;
}

//处理各种逻辑业务
bool LogicSocket::_HandleRegister(lpconnection_t connect, LPSTRUC_MSG_HEADER msg_header, char *pkg_body, unsigned short body_length) {
	//判断包体的合法性
	//LogStderr(0, "收到的是一个注册消息");
	if(pkg_body == NULL) {
		return false;
	}

	int recv_len = sizeof(STRUCT_REGISTER);
	if(recv_len != body_length) {
		return false;
	}

	Lock lock(&connect->logic_proc_mutex);
	//取得整个发送过来的数据
	LPSTRUCT_REGISTER recv_info = (LPSTRUCT_REGISTER)pkg_body;
	recv_info->type = ntohs(recv_info->type);
	recv_info->username[sizeof(recv_info->username)-1] = 0;
	recv_info->password[sizeof(recv_info->password)-1] = 0;

	//进行后续的业务处理
	//...'
	
	//给客户端返回数据
	//LogStderr(0, "准备给客户端返回信息");
	LPCOMM_PKG_HEADER pkg_header;
	MyMemory *memory = MyMemory::GetInstance();
	CRC32    *crc32  = CRC32::GetInstance();
	int send_len = sizeof(STRUCT_REGISTER);
	//分配内存
	char *send_buf = (char *)memory->AllocMemory(msg_head_len_ + pkg_head_len_ + send_len, false);
	//填充消息头
	memcpy(send_buf, msg_header, msg_head_len_);
	//填充包头
	pkg_header = (LPCOMM_PKG_HEADER)(send_buf + msg_head_len_);
	pkg_header->msg_code = _CMD_REGISTER;
	pkg_header->msg_code = htons(pkg_header->msg_code);
	pkg_header->pkg_len  = htons(pkg_header->pkg_len);
	//填充包体
	LPSTRUCT_REGISTER send_info = (LPSTRUCT_REGISTER)(send_buf + msg_head_len_ + pkg_head_len_);

	pkg_header->crc32 = crc32->GetCrc((unsigned char *)send_info, send_len);
	pkg_header->crc32 = htonl(pkg_header->crc32);
	
	MsgSend(send_buf);
	return true;
}

bool LogicSocket::_HandleLogIn(lpconnection_t connect, LPSTRUC_MSG_HEADER msg_header, char *pkg_body, unsigned short body_length) {
	//LogStderr(0, "收到的是一个登录的消息");
	if(pkg_body == NULL) {
		return false;
	}

	int recv_len = sizeof(STRUCT_LOGIN);
	if(recv_len != body_length) {
		return false;
	}
	Lock lock(&connect->logic_proc_mutex);

	LPSTRUCT_LOGIN recv_info = (LPSTRUCT_LOGIN)pkg_body;
	recv_info->username[sizeof(recv_info->username)-1] = 0;
	recv_info->password[sizeof(recv_info->password)-1] = 0;

	//处理业务
	//...
	//
	//返回给客户端
	LPCOMM_PKG_HEADER pkg_header;
	MyMemory *memory = MyMemory::GetInstance();
	CRC32    *crc32  = CRC32::GetInstance();

	int send_len = sizeof(STRUCT_LOGIN);
	char *send_buf = (char *)memory->AllocMemory(msg_head_len_ + pkg_head_len_ + send_len, false);
	memcpy(send_buf, msg_header, msg_head_len_);
	pkg_header = (LPCOMM_PKG_HEADER)(send_buf + msg_head_len_);
	pkg_header->msg_code = _CMD_LOGIN;
	pkg_header->msg_code = htons(pkg_header->msg_code);
	pkg_header->pkg_len  = htons(pkg_head_len_ + send_len);
	LPSTRUCT_LOGIN send_info = (LPSTRUCT_LOGIN)(send_buf + msg_head_len_ + msg_head_len_);
	pkg_header->crc32 = crc32->GetCrc((unsigned char *)send_info, send_len);
	pkg_header->crc32 = htonl(pkg_header->crc32);

	MsgSend(send_buf);
	return true;
}

bool LogicSocket::_HandlePing(lpconnection_t connect, LPSTRUC_MSG_HEADER msg_header, char *pkg_body, unsigned short body_length) {
	//LogStderr(0, "收到的是一个ping消息");
	if(body_length != 0) {
		return false;
	}
	Lock lock(&connect->logic_proc_mutex);
	connect->last_ping_time = time(NULL);
	SendNoBodyPkgToClient(msg_header, _CMD_PING);
	return true;
}

